home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / tools / indent.lha / indent / lexi.c < prev    next >
C/C++ Source or Header  |  1992-07-06  |  21KB  |  664 lines

  1. /*
  2.  * Copyright (c) 1985 Sun Microsystems, Inc.
  3.  * Copyright (c) 1980 The Regents of the University of California.
  4.  * Copyright (c) 1976 Board of Trustees of the University of Illinois.
  5.  * All rights reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms are permitted
  8.  * provided that the above copyright notice and this paragraph are
  9.  * duplicated in all such forms and that any documentation,
  10.  * advertising materials, and other materials related to such
  11.  * distribution and use acknowledge that the software was developed
  12.  * by the University of California, Berkeley, the University of Illinois,
  13.  * Urbana, and Sun Microsystems, Inc.  The name of either University
  14.  * or Sun Microsystems may not be used to endorse or promote products
  15.  * derived from this software without specific prior written permission.
  16.  * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
  17.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  18.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  19.  */
  20.  
  21. #ifndef lint
  22. # ifndef OS2
  23.     static char sccsid[] = "@(#)lexi.c    6.0 (Berkeley) 92/06/15";
  24. # endif
  25. #endif                          /* not lint */
  26.  
  27. /*
  28.  * Here we have the token scanner for indent.  It scans off one token and puts
  29.  * it in the global variable "token".  It returns a code, indicating the type
  30.  * of token scanned.
  31.  */
  32.  
  33. #include "globals.h"
  34. #include "codes.h"
  35. #include <ctype.h>
  36.  
  37. #ifdef OS2                      /* or MSDOS */
  38. #include <string.h>
  39. #endif
  40.  
  41. typedef enum char_type
  42. {
  43.     alphanum = 1,
  44.     opchar = 3,
  45.     colonchar = 4
  46. } char_type;
  47.  
  48. struct templ
  49. {
  50.     char *rwd;
  51.     int rwcode;
  52.     cplus_flag cplus;
  53. };
  54.  
  55. struct templ specials[100] =
  56. {
  57.     "switch", 1, c_and_cplus,
  58.     "case", 2, c_and_cplus,
  59.     "break", 0, c_and_cplus,
  60.     "struct", 3, c_and_cplus,
  61.     "union", 3, c_and_cplus,
  62.     "enum", 3, c_and_cplus,
  63.     "default", 2, c_and_cplus,
  64.     "int", 4, c_and_cplus,
  65.     "char", 4, c_and_cplus,
  66.     "float", 4, c_and_cplus,
  67.     "double", 4, c_and_cplus,
  68.     "long", 4, c_and_cplus,
  69.     "short", 4, c_and_cplus,
  70.     "typedef", 8, c_and_cplus,
  71.     "unsigned", 4, c_and_cplus,
  72.     "register", 4, c_and_cplus,
  73.     "static", 4, c_and_cplus,
  74.     "global", 4, c_and_cplus,
  75.     "extern", 4, c_and_cplus,
  76.     "void", 4, c_and_cplus,
  77.     "goto", 0, c_and_cplus,
  78.     "return", 0, c_and_cplus,
  79.     "if", 5, c_and_cplus,
  80.     "while", 5, c_and_cplus,
  81.     "for", 5, c_and_cplus,
  82.     "else", 6, c_and_cplus,
  83.     "do", 6, c_and_cplus,
  84.     "sizeof", 7, c_and_cplus,
  85.     "class", 3, cplus_only,
  86.     "public", 2, cplus_only,
  87.     "private", 2, cplus_only,
  88.     "protected", 2, cplus_only,
  89.     "volatile", 4, c_and_cplus,
  90.  
  91.     0, 0
  92. };
  93.  
  94. char chartype[128] =
  95. {                               /* this is used to facilitate the decision of
  96.                                    what type (alphanumeric, operator) each
  97.                                    character is */
  98.     0, 0, 0, 0, 0, 0, 0, 0,
  99.     0, 0, 0, 0, 0, 0, 0, 0,
  100.     0, 0, 0, 0, 0, 0, 0, 0,
  101.     0, 0, 0, 0, 0, 0, 0, 0,
  102.     0, 3, 0, 0, 1, 3, 3, 0,
  103.     0, 0, 3, 3, 0, 3, 0, 3,
  104.     1, 1, 1, 1, 1, 1, 1, 1,
  105.     1, 1, 4, 0, 3, 3, 3, 3,
  106.     0, 1, 1, 1, 1, 1, 1, 1,
  107.     1, 1, 1, 1, 1, 1, 1, 1,
  108.     1, 1, 1, 1, 1, 1, 1, 1,
  109.     1, 1, 1, 0, 0, 0, 3, 1,
  110.     0, 1, 1, 1, 1, 1, 1, 1,
  111.     1, 1, 1, 1, 1, 1, 1, 1,
  112.     1, 1, 1, 1, 1, 1, 1, 1,
  113.     1, 1, 1, 0, 3, 0, 3, 0
  114. };
  115.  
  116.  
  117.  
  118. #ifdef ANSIC
  119. int lexi(void)
  120. #else
  121. int lexi()
  122. #endif
  123. {
  124.     register char *tok;         /* local pointer to next char in token */
  125.     int unary_delim;            /* this is set to 1 if the current token
  126.                                 
  127.                                 forces a following operator to be unary */
  128.     static int last_code;       /* the last token type returned */
  129.     static int l_struct;        /* set to 1 if the last token was 'struct' */
  130.     static int l_struct_start;  /* set at struct, cleared at { or ; */
  131.     static int l_class;         /* in c++, class name coming next. */
  132.     int code;                   /* internal code to be returned */
  133.     char qchar;                 /* the delimiter character for a string */
  134.  
  135.     tok = token;                /* point to start of place to save token */
  136.     unary_delim = false;
  137.     ps.col_1 = ps.last_nl;      /* tell world that this token started in column
  138.                                    1 iff the last thing scanned was nl */
  139.     ps.last_nl = false;
  140.  
  141.     while (*buf_ptr == ' ' || *buf_ptr == '\t')
  142.     {                           /* get rid of blanks */
  143.         ps.col_1 = false;       /* leading blanks imply token is not in column
  144.                                    1 */
  145.         if (++buf_ptr >= buf_end)
  146.             fill_buffer();
  147.     }
  148.  
  149.     /* Scan an alphanumeric token */
  150.     /* In c++, :: starting token is aok, as is ~ sometimes */
  151.     /* well, int x = ~y; will work oddly here */
  152.     if (((char_type) chartype[*buf_ptr] == alphanum || buf_ptr[0] == '.' && isdigit(buf_ptr[1])) ||
  153.         (cplus && buf_ptr[0] == ':' && buf_ptr[1] == ':') ||
  154.         (cplus && ps.in_decl && *buf_ptr == '~'
  155.          && (char_type) chartype[buf_ptr[1]] == alphanum) /* destructors in
  156.                                                              classdefs */
  157.         )
  158.     {
  159.         /*
  160.            we have a character or number
  161.         */
  162.         register char *j;       /* used for searching thru list of
  163.                                 
  164.                                 reserved words */
  165.         register struct templ *p;
  166.  
  167.         if (isdigit(*buf_ptr) || buf_ptr[0] == '.' && isdigit(buf_ptr[1]))
  168.         {
  169.             int seendot = 0, seenexp = 0;
  170.  
  171.             if (*buf_ptr == '0' &&
  172.                 (buf_ptr[1] == 'x' || buf_ptr[1] == 'X'))
  173.             {
  174.                 *tok++ = *buf_ptr++;
  175.                 *tok++ = *buf_ptr++;
  176.                 while (isxdigit(*buf_ptr))
  177.                     *tok++ = *buf_ptr++;
  178.             }
  179.             else
  180.                 while (1)
  181.                 {
  182.                     if (*buf_ptr == '.')
  183.                         if (seendot)
  184.                             break;
  185.                         else
  186.                             seendot++;
  187.                     *tok++ = *buf_ptr++;
  188.                     if (!isdigit(*buf_ptr) && *buf_ptr != '.')
  189.                         if ((*buf_ptr != 'E' && *buf_ptr != 'e') || seenexp)
  190.                             break;
  191.                         else
  192.                         {
  193.                             seenexp++;
  194.                             seendot++;
  195.                             *tok++ = *buf_ptr++;
  196.                             if (*buf_ptr == '+' || *buf_ptr == '-')
  197.                                 *tok++ = *buf_ptr++;
  198.                         }
  199.                 }
  200.             if (*buf_ptr == 'L' || *buf_ptr == 'l')
  201.                 *tok++ = *buf_ptr++;
  202.         }
  203.         else
  204.         {
  205.             int first;
  206.  
  207.             first = 1;
  208.             while ((char_type) chartype[*buf_ptr] == alphanum ||
  209.                    (buf_ptr[0] == ':' && buf_ptr[1] == ':' && cplus) ||
  210.                    (cplus && first && buf_ptr[0] == '~'))
  211.             {                   /* copy it over */
  212.                 int colonp;
  213.  
  214.                 first = 0;
  215.                 colonp = *buf_ptr == ':';
  216.                 *tok++ = *buf_ptr++;
  217.                 if (colonp)
  218.                 {
  219.                     *tok++ = *buf_ptr++;
  220.                     /* foo::~foo */
  221.                     if (*buf_ptr == '~')
  222.                         *tok++ = *buf_ptr++;
  223.                     colonp = 0;
  224.                 }
  225.                 if (buf_ptr >= buf_end)
  226.                     fill_buffer();
  227.             }
  228.         }
  229.         *tok++ = '\0';
  230.         while (*buf_ptr == ' ' || *buf_ptr == '\t')
  231.         {                       /* get rid of blanks */
  232.             if (++buf_ptr >= buf_end)
  233.                 fill_buffer();
  234.         }
  235.         ps.its_a_keyword = false;
  236.         ps.sizeof_keyword = false;
  237.         if (l_struct)
  238.         {                       /* if last token was 'struct', then this token
  239.                                    should be treated as a declaration */
  240.             if (l_class)
  241.                 addkey(tok, 4);
  242.             l_class = false;
  243.             l_struct = false;
  244.             last_code = ident;
  245.             ps.last_u_d = true;
  246.             return (decl);
  247.         }
  248.         ps.last_u_d = false;    /* Operator after indentifier is binary */
  249.         last_code = ident;      /* Remember that this is the code we will
  250.                                    return */
  251.  
  252.         /*
  253.            This loop will check if the token is a keyword.
  254.         */
  255.         for (p = specials; (j = p->rwd) != 0; p++)
  256.         {
  257.             tok = token;        /* point at scanned token */
  258.             if (*j++ != *tok++ || *j++ != *tok++)
  259.                 continue;       /* This test depends on the fact that
  260.                                    identifiers are always at least 1 character
  261.                                    long (ie. the first two bytes of the
  262.                                    identifier are always meaningful) */
  263.             if (tok[-1] == 0)
  264.                 break;          /* If its a one-character identifier */
  265.             while (*tok++ == *j)
  266.                 if (*j++ == 0 &&
  267.                     (p->cplus == c_and_cplus ||
  268.                      (cplus && p->cplus == cplus_only) ||
  269.                      (!cplus && p->cplus == c_only)))
  270.                     goto found_keyword; /* I wish that C had a multi-level
  271.                                            break... */
  272.         }
  273.         if (p->rwd)
  274.         {                       /* we have a keyword */
  275.     found_keyword:
  276.             ps.its_a_keyword = true;
  277.             ps.last_u_d = true;
  278.             switch (p->rwcode)
  279.             {
  280.             case 1:            /* it is a switch */
  281.                 return (swstmt);
  282.             case 2:            /* a case or default */
  283.                 return (casestmt);
  284.  
  285.             case 3:            /* a "struct" */
  286.                 if (ps.p_l_follow)
  287.                     break;      /* inside parens: cast */
  288.                 l_struct = true;
  289.                 if (cplus)
  290.                     l_struct_start = true;
  291.                 /* automatically note keywords */
  292.                 if (cplus && strcmp(tok, "class") == 0 ||
  293.                     strcmp(tok, "struct") == 0 ||
  294.                     strcmp(tok, "union") == 0 ||
  295.                     strcmp(tok, "enum") == 0)
  296.                     l_class = true;
  297.                 /*
  298.                    Next time around, we will want to know that we have had a
  299.                    'struct'
  300.                 */
  301.             case 4:            /* one of the declaration keywords */
  302.                 if (ps.p_l_follow)
  303.                 {
  304.                     ps.cast_mask |= 1 << ps.p_l_follow;
  305.                     break;      /* inside parens: cast */
  306.                 }
  307.                 last_code = decl;
  308.                 return (decl);
  309.  
  310.             case 5:            /* if, while, for */
  311.                 return (sp_paren);
  312.  
  313.             case 6:            /* do, else */
  314.                 return (sp_nparen);
  315.  
  316.             case 7:
  317.                 ps.sizeof_keyword = true;
  318.                 return (ident);
  319.  
  320.             case 8:            /* typedef is a decl */
  321.                 last_code = decl;
  322.                 return (decl);
  323.  
  324.             default:           /* all others are treated like any other
  325.                                    identifier */
  326.                 return (ident);
  327.             }                   /* end of switch */
  328.         }                       /* end of if (found_it) */
  329.         if (*buf_ptr == '(' && ps.tos <= 1 && ps.ind_level == 0)
  330.         {
  331.             register char *tp = buf_ptr;
  332.  
  333.             while (tp < buf_end)
  334.                 if (*tp++ == ')' && *tp == ';')
  335.                     goto not_proc;
  336.             strncpy(ps.procname, token, sizeof ps.procname - 1);
  337.             ps.in_parameter_declaration = 1;
  338.     not_proc:;
  339.         }
  340.         /*
  341.            The following hack attempts to guess whether or not the current
  342.            token is in fact a declaration keyword -- one that has been typedefd
  343.         */
  344.         if (((*buf_ptr == '*' && buf_ptr[1] != '=') || isalpha(*buf_ptr) || *buf_ptr == '_')
  345.             && !ps.p_l_follow
  346.             && !ps.block_init
  347.             && (ps.last_token == rparen || ps.last_token == semicolon ||
  348.                 ps.last_token == decl ||
  349.                 ps.last_token == lbrace || ps.last_token == rbrace))
  350.         {
  351.             ps.its_a_keyword = true;
  352.             ps.last_u_d = true;
  353.             last_code = decl;
  354.             return decl;
  355.         }
  356.         if (last_code == decl)  /* if this is a declared variable, then
  357.                                    following sign is unary */
  358.             ps.last_u_d = true; /* will make "int a -1" work */
  359.         last_code = ident;
  360.         return (ident);         /* the ident is not in the list */
  361.     }                           /* end of procesing for alpanum character */
  362.     /* l l l Scan a non-alphanumeric token */
  363.  
  364.     l_class = false;            /* struct { ain't defining a class. */
  365.     *tok++ = *buf_ptr;          /* if it is only a one-character token, it is
  366.                                    moved here */
  367.     *tok = '\0';
  368.     if (++buf_ptr >= buf_end)
  369.         fill_buffer();
  370.  
  371.     switch (*token)
  372.     {
  373.     case '\n':
  374.         unary_delim = ps.last_u_d;
  375.         ps.last_nl = true;      /* remember that we just had a newline */
  376.         code = (had_eof ? 0 : newline);
  377.  
  378.         /*
  379.            if data has been exausted, the newline is a dummy, and we should
  380.            return code to stop
  381.         */
  382.         break;
  383.  
  384.     case '\'':                 /* start of quoted character */
  385.     case '"':                  /* start of string */
  386.         qchar = *token;
  387.         if (troff)
  388.         {
  389.             tok[-1] = '`';
  390.             if (qchar == '"')
  391.                 *tok++ = '`';
  392.             tok = chfont(&bodyf, &stringf, tok);
  393.         }
  394.         do
  395.         {                       /* copy the string */
  396.             while (1)
  397.             {                   /* move one character or [/<char>]<char> */
  398.                 if (*buf_ptr == '\n')
  399.                 {
  400.                     printf("%d: Unterminated literal\n", line_no);
  401.                     goto stop_lit;
  402.                 }
  403.                 *tok = *buf_ptr++;
  404.                 if (buf_ptr >= buf_end)
  405.                     fill_buffer();
  406.                 if (had_eof || ((tok - token) > (bufsize - 2)))
  407.                 {
  408.                     printf("Unterminated literal\n");
  409.                     ++tok;
  410.                     goto stop_lit;
  411.                     /* get outof literal copying loop */
  412.                 }
  413.                 if (*tok == BACKSLASH)
  414.                 {               /* if escape, copy extra char */
  415.                     if (*buf_ptr == '\n') /* check for escaped newline */
  416.                         ++line_no;
  417.                     if (troff)
  418.                     {
  419.                         *++tok = BACKSLASH;
  420.                         if (*buf_ptr == BACKSLASH)
  421.                             *++tok = BACKSLASH;
  422.                     }
  423.                     *++tok = *buf_ptr++;
  424.                     ++tok;      /* we must increment this again because we
  425.                                    copied two chars */
  426.                     if (buf_ptr >= buf_end)
  427.                         fill_buffer();
  428.                 }
  429.                 else
  430.                     break;      /* we copied one character */
  431.             }                   /* end of while (1) */
  432.         } while (*tok++ != qchar);
  433.         if (troff)
  434.         {
  435.             tok = chfont(&stringf, &bodyf, tok - 1);
  436.             if (qchar == '"')
  437.                 *tok++ = '\'';
  438.         }
  439. stop_lit:
  440.         code = ident;
  441.         break;
  442.  
  443.     case ('('):
  444.     case ('['):
  445.         unary_delim = true;
  446.         code = lparen;
  447.         break;
  448.  
  449.     case (')'):
  450.     case (']'):
  451.         code = rparen;
  452.         break;
  453.  
  454.     case '#':
  455.         unary_delim = ps.last_u_d;
  456.         code = preesc;
  457.         break;
  458.  
  459.     case '?':
  460.         unary_delim = true;
  461.         code = question;
  462.         break;
  463.  
  464.     case (':'):
  465.         if (l_struct_start)
  466.             code = ident;
  467.         else
  468.             code = colon;
  469.         unary_delim = true;
  470.         break;
  471.  
  472.     case (';'):
  473.         l_struct_start = false;
  474.         unary_delim = true;
  475.         code = semicolon;
  476.         break;
  477.  
  478.     case ('{'):
  479.         l_struct_start = false;
  480.         unary_delim = true;
  481.  
  482.         /*
  483.            if (ps.in_or_st) ps.block_init = 1;
  484.         */
  485.         /* ?    code = ps.block_init ? lparen : lbrace; */
  486.         code = lbrace;
  487.         break;
  488.  
  489.     case ('}'):
  490.         unary_delim = true;
  491.         /* ?    code = ps.block_init ? rparen : rbrace; */
  492.         code = rbrace;
  493.         break;
  494.  
  495.     case 014:                  /* a form feed */
  496.         unary_delim = ps.last_u_d;
  497.         ps.last_nl = true;      /* remember this so we can set 'ps.col_1' right */
  498.         code = form_feed;
  499.         break;
  500.  
  501.     case (','):
  502.         unary_delim = true;
  503.         code = comma;
  504.         break;
  505.  
  506.     case '.':
  507.         unary_delim = false;
  508.         code = period;
  509.         break;
  510.  
  511.     case '-':
  512.     case '+':                  /* check for -, +, --, ++ */
  513.         code = (ps.last_u_d ? unary_op : binary_op);
  514.         unary_delim = true;
  515.  
  516.         if (*buf_ptr == token[0])
  517.         {
  518.             /* check for doubled character */
  519.             *tok++ = *buf_ptr++;
  520.             /* buffer overflow will be checked at end of loop */
  521.             if (last_code == ident || last_code == rparen)
  522.             {
  523.                 code = (ps.last_u_d ? unary_op : postop);
  524.                 /* check for following ++ or -- */
  525.                 unary_delim = false;
  526.             }
  527.         }
  528.         else if (*buf_ptr == '=')
  529.             /* check for operator += */
  530.             *tok++ = *buf_ptr++;
  531.         else if (*buf_ptr == '>')
  532.         {
  533.             /* check for operator -> */
  534.             *tok++ = *buf_ptr++;
  535.             if (!pointer_as_binop)
  536.             {
  537.                 unary_delim = false;
  538.                 code = unary_op;
  539.                 ps.want_blank = false;
  540.             }
  541.         }
  542.         break;                  /* buffer overflow will be checked at end of
  543.                                    switch */
  544.  
  545.     case '=':
  546.         if (ps.in_or_st)
  547.             ps.block_init = 1;
  548. #ifdef undef
  549.         if (chartype[*buf_ptr] == opchar)
  550.         {                       /* we have two char assignment */
  551.             tok[-1] = *buf_ptr++;
  552.             if ((tok[-1] == '<' || tok[-1] == '>') && tok[-1] == *buf_ptr)
  553.                 *tok++ = *buf_ptr++;
  554.             *tok++ = '=';       /* Flip =+ to += */
  555.             *tok = 0;
  556.         }
  557. #else
  558.         if (*buf_ptr == '=')
  559.         {                       /* == */
  560.             *tok++ = '=';       /* Flip =+ to += */
  561.             buf_ptr++;
  562.             *tok = 0;
  563.         }
  564. #endif
  565.         code = binary_op;
  566.         unary_delim = true;
  567.         break;
  568.         /* can drop thru!!! */
  569.  
  570.     case '>':
  571.     case '<':
  572.     case '!':                  /* ops like <, <<, <=, !=, etc */
  573.         if (*buf_ptr == '>' || *buf_ptr == '<' || *buf_ptr == '=')
  574.         {
  575.             *tok++ = *buf_ptr;
  576.             if (++buf_ptr >= buf_end)
  577.                 fill_buffer();
  578.         }
  579.         if (*buf_ptr == '=')
  580.             *tok++ = *buf_ptr++;
  581.         code = (ps.last_u_d ? unary_op : binary_op);
  582.         unary_delim = true;
  583.         break;
  584.  
  585.     default:
  586.         if (token[0] == '/' && *buf_ptr == '*')
  587.         {
  588.             /* it is start of a C comment */
  589.             *tok++ = '*';
  590.  
  591.             if (++buf_ptr >= buf_end)
  592.                 fill_buffer();
  593.  
  594.             code = comment;
  595.             unary_delim = ps.last_u_d;
  596.             break;
  597.         }
  598.         if (token[0] == '/' && *buf_ptr == '/')
  599.         {
  600.             /* it is start of a C++ comment */
  601.             *tok++ = '/';
  602.  
  603.             if (++buf_ptr >= buf_end)
  604.                 fill_buffer();
  605.  
  606.             code = cc_commnt;
  607.             ps.cc_comment++;
  608.             unary_delim = ps.last_u_d;
  609.             break;
  610.         }
  611.         while (*(tok - 1) == *buf_ptr || *buf_ptr == '=')
  612.         {
  613.             /*
  614.                handle ||, &&, etc, and also things as in int *****i
  615.             */
  616.             *tok++ = *buf_ptr;
  617.             if (++buf_ptr >= buf_end)
  618.                 fill_buffer();
  619.         }
  620.         code = (ps.last_u_d ? unary_op : binary_op);
  621.         unary_delim = true;
  622.  
  623.  
  624.     }                           /* end of switch */
  625.     if (code != newline)
  626.     {
  627.         l_struct = false;
  628.         last_code = code;
  629.     }
  630.     if (buf_ptr >= buf_end)     /* check for input buffer empty */
  631.         fill_buffer();
  632.     ps.last_u_d = unary_delim;
  633.     *tok = '\0';                /* null terminate the token */
  634.     return (code);
  635. };
  636.  
  637. /*
  638.  * Add the given keyword to the keyword table, using val as the keyword type
  639.  */
  640. #ifdef ANSIC
  641. void addkey(char *key, int val)
  642. #else
  643. addkey(key, val)
  644.     char *key;
  645.  
  646. #endif
  647. {
  648.     register struct templ *p = specials;
  649.  
  650.     while (p->rwd)
  651.         if (p->rwd[0] == key[0] && strcmp(p->rwd, key) == 0)
  652.             return;
  653.         else
  654.             p++;
  655.     if (p >= specials + sizeof specials / sizeof specials[0])
  656.         return;                 /* For now, table overflows are silently
  657.                                    ignored */
  658.     p->rwd = key;
  659.     p->rwcode = val;
  660.     p[1].rwd = 0;
  661.     p[1].rwcode = 0;
  662.     return;
  663. }
  664.